feat: switch VirtualTable producer to use expressions field instead of deprecated values - #23672
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #23672 +/- ##
==========================================
+ Coverage 80.66% 80.74% +0.07%
==========================================
Files 1086 1096 +10
Lines 366673 373559 +6886
Branches 366673 373559 +6886
==========================================
+ Hits 295786 301629 +5843
- Misses 53263 53928 +665
- Partials 17624 18002 +378 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
vbarua
left a comment
There was a problem hiding this comment.
Thinking about this from a migration perspective, I think we need to do ship this as 2 changes:
- Release a change that switches the producer to generate VirtualTables using only the
expressionsfield. - After that is live, release the change that fully removes the old
valuesfield.
Because the producer currently emits plans using the deprecated field, we need to give users a chance to update any stored plans, and then remove support for values.
vbarua
left a comment
There was a problem hiding this comment.
Some more minor comment.
Can I tag you into this @gabotechs, it's been a minute since I looked at the name handling code.
| let expr = consumer | ||
| .consume_expression(expression, &substrait_schema) | ||
| .await?; | ||
| let expr = match expression.rex_type.as_ref() { |
There was a problem hiding this comment.
Both branches increment name_idx by 1. I think we can extract that out out before the match and expand on the comment with something like
// Top-level names are provided through schema
// Each expression consumes at least one name, and Literals may consume additional names.
name_idx += 1;to provide a bit more context about what is happening.
vbarua
left a comment
There was a problem hiding this comment.
Left one final comment, but other than that I think this is good to go.
gabotechs
left a comment
There was a problem hiding this comment.
Thanks @eliot1480! this looks good, just left a non blocking comment. Also thanks @vbarua for the review.
| .consume_expression(expression, &substrait_schema) | ||
| .await?; | ||
| let expr = match expression.rex_type.as_ref() { | ||
| Some(substrait::proto::expression::RexType::Literal(lit)) => { |
There was a problem hiding this comment.
The first questions that readers might have is:
Why does the Literal expression type needs special handling? Adding a comment with some context about why this special handling is needed can save some investigation time from readers.
Which issue does this PR close?
Rationale for this change
Since the VirtualTables.values field has been deprecated and is soon to be removed in the next substrait update, we should make sure to delete all instances of it to prevent the presence of dead code.
This PR switches the producer to generate VirtualTables using only the expressions field. A later PR will be released to fully remove all instances of the
valuesfield. The reason removal will be separate is because we want to give users a chance to update any stored plans, and then remove values.The consumer also needed an update, because since the producer only emits expressions, a new gap was introduced where expressions never uses named_struct.names to rename nested fields (structs/lists) the way the values/literal path does. So for flat/scalar columns, expressions would work fine, but for struct/list-typed columns, the consumer would silently drop original nested field names and fall back to positional defaults.
What changes are included in this PR?
Producer now emits VirtualTable.expressions for Values and EmptyRelation. Converted 17 direct virtualTable.values entries across 10 JSON test plans to virtualTable.expressions. Consumer now adds support for struct field-name preservation when reading from only expressions.
Are these changes tested?
Yes they are. Tests ran:
jq validation for JSON fixtures
Are there any user-facing changes?
No.